package com.multitrack.chromb;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.util.Log;

import com.vecore.base.lib.utils.FileUtils;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.Arrays;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

/**
 * @author JIAN
 * @create 2025/3/17
 * @Describe
 */
public class BitmapRenderer2 implements GLSurfaceView.Renderer {
    private int textureId;
    private Bitmap bitmap;
    private int program;
    private int positionHandle;
    private int textureCoordHandle;
    private int textureHandle;
    private int backgroundColorHandle;
    private float[] backgroundColor = {0.0f, 1.0f, 0.0f}; // 默认绿幕颜色

    private final float[] vertices = {
            -1.0f, -1.0f, 0.0f,
            1.0f, -1.0f, 0.0f,
            -1.0f, 1.0f, 0.0f,
            1.0f, 1.0f, 0.0f
    };

    private final float[] textureCoords = {
            0.0f, 1.0f,
            1.0f, 1.0f,
            0.0f, 0.0f,
            1.0f, 0.0f
    };

    private FloatBuffer vertexBuffer;
    private FloatBuffer textureBuffer;

    public BitmapRenderer2(Context context, Bitmap bitmap) {
        vertexShaderCode = FileUtils.readTxtFile(context, "asset:///ok/vert.txt");
        fragmentShaderCode = FileUtils.readTxtFile(context, "asset:///ok/frag.txt");
        this.bitmap = bitmap;
        vertexBuffer = ByteBuffer.allocateDirect(vertices.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        vertexBuffer.put(vertices).position(0);

        textureBuffer = ByteBuffer.allocateDirect(textureCoords.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        textureBuffer.put(textureCoords).position(0);
    }

    public void setBackgroundColor(float r, float g, float b) {
        this.backgroundColor[0] = r;
        this.backgroundColor[1] = g;
        this.backgroundColor[2] = b;
    }

    private int toleranceHandle;
    private int thresholdHandle;
    private float tolerance = 0.2f; // 默认容差
    private float threshold = 0.3f; // 默认程度

    public void setTolerance(float tolerance) {
        this.tolerance = tolerance;
    }

    public void setThreshold(float threshold) {
        this.threshold = threshold;
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        textureId = loadTexture(bitmap);
        program = createProgram(loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode),
                loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode));
        positionHandle = GLES20.glGetAttribLocation(program, "aPosition");
        textureCoordHandle = GLES20.glGetAttribLocation(program, "aTextureCoord");
        textureHandle = GLES20.glGetUniformLocation(program, "uTexture");
        backgroundColorHandle = GLES20.glGetUniformLocation(program, "uBackgroundColor");
        toleranceHandle = GLES20.glGetUniformLocation(program, "uTolerance");
        thresholdHandle = GLES20.glGetUniformLocation(program, "uThreshold");
    }

    private static final String TAG = "BitmapRenderer2";

    private Bitmap out;
    private boolean bSaveOnce = false;

    public void prepareSave() {
        bSaveOnce = true;
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        GLES20.glClearColor(1f, 0, 0, 1.0f);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        GLES20.glUseProgram(program);


        GLES20.glEnableVertexAttribArray(positionHandle);
        GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);

        GLES20.glEnableVertexAttribArray(textureCoordHandle);
        GLES20.glVertexAttribPointer(textureCoordHandle, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
        GLES20.glUniform1i(textureHandle, 0);
        Log.e(TAG, "onDrawFrame: " + Arrays.toString(backgroundColor));

        GLES20.glUniform1f(toleranceHandle, tolerance);
        GLES20.glUniform1f(thresholdHandle, threshold);

        // 设置背景色
        GLES20.glUniform3f(backgroundColorHandle, backgroundColor[0], backgroundColor[1], backgroundColor[2]);

        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
        GLES20.glDisableVertexAttribArray(positionHandle);
        GLES20.glDisableVertexAttribArray(textureCoordHandle);
        if (bSaveOnce) {
            bSaveOnce = false;
            out = saveFrame(nOutWidth, nOutHeight);
        }
    }

    public Bitmap getOut() {
        return out;
    }

    private int nOutWidth, nOutHeight;

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
        nOutWidth = width;
        nOutHeight = height;
    }


    public Bitmap saveFrame(int width, int height) {
        // Allocate a buffer to hold the pixel data
        ByteBuffer buffer = ByteBuffer.allocateDirect(width * height * 4);
        buffer.order(ByteOrder.nativeOrder());

        // Read the pixels from the framebuffer
        GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buffer);

        // Create a bitmap and copy the buffer data into it
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        buffer.rewind();
        bitmap.copyPixelsFromBuffer(buffer);

        // Flip the bitmap vertically
        Matrix matrix = new Matrix();
        matrix.preScale(1.0f, -1.0f);
        Bitmap flippedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);

        return flippedBitmap;
//        return bitmap;
    }


    private int loadTexture(Bitmap bitmap) {
        int[] textureIds = new int[1];
        GLES20.glGenTextures(1, textureIds, 0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[0]);
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        return textureIds[0];
    }

    private int createProgram(int vertexShader, int fragmentShader) {
        int program = GLES20.glCreateProgram();
        GLES20.glAttachShader(program, vertexShader);
        GLES20.glAttachShader(program, fragmentShader);
        GLES20.glLinkProgram(program);
        return program;
    }

    private int loadShader(int type, String shaderCode) {
        int shader = GLES20.glCreateShader(type);
        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);
        return shader;
    }

    private final String vertexShaderCode;
    private final String fragmentShaderCode;


}
